
#ifndef     __WEBCLIENT_H__
#define     __WEBCLIENT_H__


#include "../../inc/sys_cfg.h"
#include "../../inc/pt_include.h"
#include "../../inc/pt_printk.h"

#define BK_OK                      0
#define BK_FAIL                    -1

#define BK_ERR_COMMON_BASE         (-0x1000)
#define BK_ERR_WIFI_BASE           (-0x1200)
#define BK_ERR_WPA_BASE            (-0x1400)
#define BK_ERR_BLE_BASE            (-0x1600)
#define BK_ERR_RWNX_BASE           (-0x1800)
#define BK_ERR_HITF_BASE           (-0x1900)
#define BK_ERR_EVENT_BASE          (-0x1b00)
#define BK_ERR_NETIF_BASE          (-0x1c00)
#define BK_ERR_PWM_BASE            (-0x1d00)
#define BK_ERR_PWM_HAL_BASE        (-0x1e00)
#define BK_ERR_TIMER_BASE          (-0x1f00)
#define BK_ERR_GPIO_BASE           (-0x2000)
#define BK_ERR_DMA_BASE            (-0x2100)
#define BK_ERR_DMA_HAL_BASE        (-0x2200)
#define BK_ERR_RF_BASE             (-0x2300)
#define BK_ERR_UART_BASE           (-0x2400)
#define BK_ERR_INT_BASE            (-0x2500)
#define BK_ERR_WDT_BASE            (-0x2600)
#define BK_ERR_TRNG_BASE           (-0x2700)
#define BK_ERR_EFUSE_BASE          (-0x2800)
#define BK_ERR_MAC_BASE            (-0x2820)
#define BK_ERR_TEMPD_BASE          (-0x2840)
#define BK_ERR_ADC_BASE            (-0x2900)
#define BK_ERR_SPI_BASE            (-0x2a00)
#define BK_ERR_MAILBOX_BASE        (-0x2b00)
#define BK_ERR_QSPI_BASE           (-0x2c00)
#define BK_ERR_I2C_BASE            (-0x2d00)
#define BK_ERR_VAULT_BASE          (-0x2e00)
#define BK_ERR_AON_RTC_BASE        (-0x2f00)
#define BK_ERR_JPEG_BASE           (-0x3000)
#define BK_ERR_AUD_BASE            (-0x3100)
#define BK_ERR_FFT_BASE            (-0x3200)
#define BK_ERR_TOUCH_BASE          (-0x3300)
#define BK_ERR_I2S_BASE            (-0x3400)
#define BK_ERR_CALENDAR_BASE       (-0x3500)
#define BK_ERR_SBC_BASE            (-0x3600)
#define BK_ERR_FLASH_BASE          (-0x3700)
#define BK_ERR_SDIO_BASE           (-0x3800)
#define BK_ERR_SDIO_HOST_BASE      (-0x3900)
#define BK_ERR_MPC_BASE            (-0x3a00)
#define BK_ERR_PSRAM_BASE          (-0x3b00)
#define BK_ERR_PRRO_BASE           (-0x3c00)
#define BK_ERR_AON_WDT_BASE        (-0x3d00)
#define BK_ERR_JPEGDEC_BASE        (-0x3e00)
#define BK_ERR_LCD_BASE            (-0x3f00)
#define BK_ERR_DMA2D_BASE          (-0x4000)
#define BK_ERR_YUV_BUF_BASE        (-0x4100)
#define BK_ERR_UVC_BASE            (-0x4200)
#define BK_ERR_H264_BASE           (-0x4300)
#define BK_ERR_USB_BASE            (-0x4400)
#define BK_ERR_OTP_BASE            (-0x4500)
#define BK_ERR_CKMN_BASE           (-0x4600)
#define BK_ERR_LIN_BASE            (-0x4700)
#define BK_ERR_SCR_BASE            (-0x4800)

#define BK_ERR_RTOS_BASE           (-0x1a2c) //-6700

#define BK_ERR_NOT_INIT            (BK_ERR_COMMON_BASE)
#define BK_ERR_PARAM               (BK_ERR_COMMON_BASE - 1)
#define BK_ERR_NOT_FOUND           (BK_ERR_COMMON_BASE - 2)
#define BK_ERR_OPEN                (BK_ERR_COMMON_BASE - 3)
#define BK_ERR_IN_PROGRESS         (BK_ERR_COMMON_BASE - 4)
#define BK_ERR_NO_MEM              (BK_ERR_COMMON_BASE - 5)
#define BK_ERR_TIMEOUT             (BK_ERR_COMMON_BASE - 6)
#define BK_ERR_STATE               (BK_ERR_COMMON_BASE - 7)
#define BK_ERR_TRY_AGAIN           (BK_ERR_COMMON_BASE - 8)
#define BK_ERR_NULL_PARAM          (BK_ERR_COMMON_BASE - 9)
#define BK_ERR_NOT_SUPPORT         (BK_ERR_COMMON_BASE - 10)
#define BK_ERR_BUSY                (BK_ERR_COMMON_BASE - 11)
#define BK_ERR_PATH                (BK_ERR_COMMON_BASE - 12)

#define  EPERM            1  /* Operation not permitted */
#define  ENOENT           2  /* No such file or directory */
#define  ESRCH            3  /* No such process */
#define  EINTR            4  /* Interrupted system call */
#define  EIO              5  /* I/O error */
#define  ENXIO            6  /* No such device or address */
#define  E2BIG            7  /* Arg list too long */
#define  ENOEXEC          8  /* Exec format error */
#define  EBADF            9  /* Bad file number */
#define  ECHILD          10  /* No child processes */
#define  EAGAIN          11  /* Try again */
#define  ENOMEM          12  /* Out of memory */
#define  EACCES          13  /* Permission denied */
#define  EFAULT          14  /* Bad address */
#define  ENOTBLK         15  /* Block device required */
#define  EBUSY           16  /* Device or resource busy */
#define  EEXIST          17  /* File exists */
#define  EXDEV           18  /* Cross-device link */
#define  ENODEV          19  /* No such device */
#define  ENOTDIR         20  /* Not a directory */
#define  EISDIR          21  /* Is a directory */
#define  EINVAL          22  /* Invalid argument */
#define  ENFILE          23  /* File table overflow */
#define  EMFILE          24  /* Too many open files */
#define  ENOTTY          25  /* Not a typewriter */
#define  ETXTBSY         26  /* Text file busy */
#define  EFBIG           27  /* File too large */
#define  ENOSPC          28  /* No space left on device */
#define  ESPIPE          29  /* Illegal seek */
#define  EROFS           30  /* Read-only file system */
#define  EMLINK          31  /* Too many links */
#define  EPIPE           32  /* Broken pipe */
#define  EDOM            33  /* Math argument out of domain of func */
#define  ERANGE          34  /* Math result not representable */
#define  EDEADLK         35  /* Resource deadlock would occur */
#define  ENAMETOOLONG    36  /* File name too long */
#define  ENOLCK          37  /* No record locks available */
#define  ENOSYS          38  /* Function not implemented */
#define  ENOTEMPTY       39  /* Directory not empty */
#define  ELOOP           40  /* Too many symbolic links encountered */
#define  EWOULDBLOCK     EAGAIN  /* Operation would block */
#define  ENOMSG          42  /* No message of desired type */
#define  EIDRM           43  /* Identifier removed */
#define  ECHRNG          44  /* Channel number out of range */
#define  EL2NSYNC        45  /* Level 2 not synchronized */
#define  EL3HLT          46  /* Level 3 halted */
#define  EL3RST          47  /* Level 3 reset */
#define  ELNRNG          48  /* Link number out of range */
#define  EUNATCH         49  /* Protocol driver not attached */
#define  ENOCSI          50  /* No CSI structure available */
#define  EL2HLT          51  /* Level 2 halted */
#define  EBADE           52  /* Invalid exchange */
#define  EBADR           53  /* Invalid request descriptor */
#define  EXFULL          54  /* Exchange full */
#define  ENOANO          55  /* No anode */
#define  EBADRQC         56  /* Invalid request code */
#define  EBADSLT         57  /* Invalid slot */

#define  EDEADLOCK       EDEADLK

#define  EBFONT          59  /* Bad font file format */
#define  ENOSTR          60  /* Device not a stream */
#define  ENODATA         61  /* No data available */
#define  ETIME           62  /* Timer expired */
#define  ENOSR           63  /* Out of streams resources */
#define  ENONET          64  /* Machine is not on the network */
#define  ENOPKG          65  /* Package not installed */
#define  EREMOTE         66  /* Object is remote */
#define  ENOLINK         67  /* Link has been severed */
#define  EADV            68  /* Advertise error */
#define  ESRMNT          69  /* Srmount error */
#define  ECOMM           70  /* Communication error on send */
#define  EPROTO          71  /* Protocol error */
#define  EMULTIHOP       72  /* Multihop attempted */
#define  EDOTDOT         73  /* RFS specific error */
#define  EBADMSG         74  /* Not a data message */
#define  EOVERFLOW       75  /* Value too large for defined data type */
#define  ENOTUNIQ        76  /* Name not unique on network */
#define  EBADFD          77  /* File descriptor in bad state */
#define  EREMCHG         78  /* Remote address changed */
#define  ELIBACC         79  /* Can not access a needed shared library */
#define  ELIBBAD         80  /* Accessing a corrupted shared library */
#define  ELIBSCN         81  /* .lib section in a.out corrupted */
#define  ELIBMAX         82  /* Attempting to link in too many shared libraries */
#define  ELIBEXEC        83  /* Cannot exec a shared library directly */
#define  EILSEQ          84  /* Illegal byte sequence */
#define  ERESTART        85  /* Interrupted system call should be restarted */
#define  ESTRPIPE        86  /* Streams pipe error */
#define  EUSERS          87  /* Too many users */
#define  ENOTSOCK        88  /* Socket operation on non-socket */
#define  EDESTADDRREQ    89  /* Destination address required */
#define  EMSGSIZE        90  /* Message too long */
#define  EPROTOTYPE      91  /* Protocol wrong type for socket */
#define  ENOPROTOOPT     92  /* Protocol not available */
#define  EPROTONOSUPPORT 93  /* Protocol not supported */
#define  ESOCKTNOSUPPORT 94  /* Socket type not supported */
#define  EOPNOTSUPP      95  /* Operation not supported on transport endpoint */
#define  EPFNOSUPPORT    96  /* Protocol family not supported */
#define  EAFNOSUPPORT    97  /* Address family not supported by protocol */
#define  EADDRINUSE      98  /* Address already in use */
#define  EADDRNOTAVAIL   99  /* Cannot assign requested address */
#define  ENETDOWN       100  /* Network is down */
#define  ENETUNREACH    101  /* Network is unreachable */
#define  ENETRESET      102  /* Network dropped connection because of reset */
#define  ECONNABORTED   103  /* Software caused connection abort */
#define  ECONNRESET     104  /* Connection reset by peer */
#define  ENOBUFS        105  /* No buffer space available */
#define  EISCONN        106  /* Transport endpoint is already connected */
#define  ENOTCONN       107  /* Transport endpoint is not connected */
#define  ESHUTDOWN      108  /* Cannot send after transport endpoint shutdown */
#define  ETOOMANYREFS   109  /* Too many references: cannot splice */
#define  ETIMEDOUT      110  /* Connection timed out */
#define  ECONNREFUSED   111  /* Connection refused */
#define  EHOSTDOWN      112  /* Host is down */
#define  EHOSTUNREACH   113  /* No route to host */
#define  EALREADY       114  /* Operation already in progress */
#define  EINPROGRESS    115  /* Operation now in progress */
#define  ESTALE         116  /* Stale NFS file handle */
#define  EUCLEAN        117  /* Structure needs cleaning */
#define  ENOTNAM        118  /* Not a XENIX named type file */
#define  ENAVAIL        119  /* No XENIX semaphores available */
#define  EISNAM         120  /* Is a named type file */
#define  EREMOTEIO      121  /* Remote I/O error */
#define  EDQUOT         122  /* Quota exceeded */

#define  ENOMEDIUM      123  /* No medium found */
#define  EMEDIUMTYPE    124  /* Wrong medium type */

#define BK_ASSERT(exp)                                       \
do {                                                         \
    if ( !(exp) ) {                                          \
         ;                                                   \
    }                                                        \
} while (0)

#if defined(WEBCLIENT_USING_MBED_TLS) || defined(WEBCLIENT_USING_SAL_TLS)
#include <tls_client.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

#ifndef web_malloc
#define web_malloc                     malloc
#endif

#ifndef web_calloc
#define web_calloc                     calloc
#endif

#ifndef web_realloc
#define web_realloc                    realloc
#endif

#ifndef web_free
#define web_free                       free
#endif

#ifndef web_strdup
#define web_strdup                    strdup
#endif

#ifndef closesocket
#define closesocket                   close
#endif

#define WEBCLIENT_SW_VERSION           "2.2.0"
#define WEBCLIENT_SW_VERSION_NUM       0x20200

#define WEBCLIENT_HEADER_BUFSZ         4096
#define WEBCLIENT_RESPONSE_BUFSZ       4096

enum WEBCLIENT_STATUS
{
    WEBCLIENT_OK,
    WEBCLIENT_ERROR,
    WEBCLIENT_TIMEOUT,
    WEBCLIENT_NOMEM,
    WEBCLIENT_NOSOCKET,
    WEBCLIENT_NOBUFFER,
    WEBCLIENT_CONNECT_FAILED,
    WEBCLIENT_DISCONNECT,
    WEBCLIENT_FILE_ERROR,
};

enum WEBCLIENT_METHOD
{
    WEBCLIENT_USER_METHOD,
    WEBCLIENT_GET,
    WEBCLIENT_POST,
};

struct  webclient_header
{
    char *buffer;
    size_t length;                      /* content header buffer size */

    size_t size;                        /* maximum support header size */
};

struct webclient_session
{
    struct webclient_header *header;    /* webclient response header information */
    int socket;
    int resp_status;

    char *host;                         /* server host */
    char *req_url;                      /* HTTP request address*/

    int chunk_sz;
    int chunk_offset;

    int content_length;
    char *Cookie;
    size_t content_remainder;           /* remainder of content length */

    int is_tls;                   /* HTTPS connect */
#ifdef WEBCLIENT_USING_MBED_TLS
    MbedTLSSession *tls_session;        /* mbedtls connect session */
#endif
};

/* create webclient session and set header response size */
struct webclient_session *webclient_session_create(size_t header_sz);

/* send HTTP GET request */
int webclient_get(struct webclient_session *session, const char *URI);
int webclient_get_position(struct webclient_session *session, const char *URI, int position);

/* send HTTP POST request */
int webclient_post(struct webclient_session *session, const char *URI, const void *post_data, size_t data_len);

/* close and release wenclient session */
int webclient_close(struct webclient_session *session);

int webclient_set_timeout(struct webclient_session *session, int millisecond);

/* send or receive data from server */
int webclient_read(struct webclient_session *session, void *buffer, size_t size);
int webclient_write(struct webclient_session *session, const void *buffer, size_t size);

/* webclient GET/POST header buffer operate by the header fields */
int webclient_header_fields_add(struct webclient_session *session, const char *fmt, ...);
const char *webclient_header_fields_get(struct webclient_session *session, const char *fields);

/* send HTTP POST/GET request, and get response data */
int webclient_response(struct webclient_session *session, void **response, size_t *resp_len);
int webclient_request(const char *URI, const char *header, const void *post_data, size_t data_len, void **response, size_t *resp_len);
int webclient_request_header_add(char **request_header, const char *fmt, ...);
int webclient_resp_status_get(struct webclient_session *session);
int webclient_content_length_get(struct webclient_session *session);


#ifdef  __cplusplus
    }
#endif


int test_http(void);


#endif